﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace PrintServerTables
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public Servers servers;
        private string sDir;

        public MainWindow()
        {
            InitializeComponent();

            try
            {
                servers = new Servers();
                string sExec = Assembly.GetExecutingAssembly().Location;
                int i = sExec.LastIndexOf("\\");
                sDir = sExec.Substring(0, i) + "\\Data\\servers.xml";
                btnSave.IsEnabled = false;
                if (File.Exists(sDir))
                {
                    StreamReader sr = new StreamReader(sDir);
                    string sXml = sr.ReadToEnd();
                    sr.Close();
                    servers.Load(sXml);
                    grdServers.ItemsSource = servers;
                }
            }
            catch (Exception ex)
            {
            }
        }

        private void btnClose_Click(object sender, RoutedEventArgs e)
        {
            if (btnSave.IsEnabled == true)
            {
                if (MessageBox.Show("There are unsaved changes.\nDo you wish to save them?", "Close Application",
                    MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
                    return; 
            }

            this.Close();
        }

        private void btnAdd_Click(object sender, RoutedEventArgs e)
        {
            wndServer wserver = new wndServer();
            wserver.theParent = this;
            wserver.ShowDialog();
            if (wserver.DialogResult == true)
            {
                Server srv = new Server();
                srv.name = wserver.theServer.name;
                srv.location = wserver.theServer.location;
                srv.web = wserver.theServer.web;
                srv.port = wserver.theServer.port;
                srv.privateIp = wserver.theServer.privateIp;
                srv.publicIp = wserver.theServer.publicIp;
                servers.Add(srv);
                grdServers.ItemsSource = null;
                grdServers.ItemsSource = servers;
                btnSave.IsEnabled = true;
            }
        }

        private void btnDelete_Click(object sender, RoutedEventArgs e)
        {
            if (grdServers.SelectedItems.Count == 0)
            {
                MessageBox.Show("There is no server to delete!", "Deleta a server", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            int i = servers.IndexOf((Server)grdServers.SelectedItem);
            servers.RemoveAt(i);
            grdServers.ItemsSource = null;
            grdServers.ItemsSource = servers;
            btnSave.IsEnabled = true;
        }

        private void grdServers_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
        {
            grdServers.CancelEdit(DataGridEditingUnit.Cell);
        }

        private void grdServers_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            wndServer wserver = new wndServer();
            int i = servers.IndexOf((Server)grdServers.SelectedItem);
            Server srv = servers[i];
            wserver.theServer = srv;
            wserver.theParent = this;
            wserver.ShowDialog();

            if (wserver.DialogResult == true)
            {
                srv.name = wserver.theServer.name;
                srv.location = wserver.theServer.location;
                srv.web = wserver.theServer.web;
                srv.port = wserver.theServer.port;
                srv.privateIp = wserver.theServer.privateIp;
                srv.publicIp = wserver.theServer.publicIp;
                grdServers.ItemsSource = null;
                grdServers.ItemsSource = servers;
                btnSave.IsEnabled = true;
            }

            grdServers.SelectedIndex = i;
        }

        private void btnSave_Click(object sender, RoutedEventArgs e)
        {
            StreamWriter sWriter = new StreamWriter(sDir, false);
            sWriter.WriteLine("<SERVERS>");
            foreach (Server s in servers)
            {
                sWriter.WriteLine(s.ToString());
            }

            sWriter.WriteLine("</SERVERS>");
            sWriter.Close();
            btnSave.IsEnabled = false;
        }
    }

    public class Server
    {
        public string name { get; set; }
        public string location { get; set; }
        public string privateIp { get; set; }
        public string publicIp { get; set; }
        public string web { get; set; }
        public string port { get; set; }

        public Server()
        {
            name = "";
            location = "";
            privateIp = "";
            publicIp = "";
            web = "";
            port = "";
        }

        public Server(XElement xElement)
        {
            name = xElement.Attribute("Name").Value;
            location = xElement.Attribute("Location").Value;
            privateIp = xElement.Attribute("PrivateIp").Value;
            publicIp = xElement.Attribute("PublicIp").Value;
            web = xElement.Attribute("Web").Value;
            port = xElement.Attribute("Port").Value;
        }

        public XElement xServer
        {
            get
            {
                return new XElement("Server",
                new XAttribute("Name", name),
                new XAttribute("Location", location),
                new XAttribute("PrivateIp", privateIp),
                new XAttribute("PublicIp", publicIp),
                new XAttribute("Web", web),
                new XAttribute("Port", port));
            }
        }

        public override string ToString()
        {
            string sXml = "<SERVER ";
            sXml += (" Name=\"" + this.name + @"""");
            sXml += (" Location=\"" + this.location + @"""");
            sXml += (" PrivateIp=\"" + this.privateIp + @"""");
            sXml += (" PublicIp=\"" + this.publicIp + @"""");
            sXml += (" Web=\"" + this.web + @"""");
            sXml += (" Port=\"" + this.port + @"""");
            sXml += " />";
            return sXml;
        }

    }

    public class Servers : ObservableCollection<Server>
    {
        public Servers()
        {
        }

        public void Load(string strXML)
        {
            var vServer = from s in XElement.Parse(strXML).Elements("SERVER") select new Server(s);
            foreach (Server ss in vServer)
                Add(ss);
        }
    }

    public sealed class VisualUtilities
    {
        private int indentDepth;
        public DataTable dtElements;

        public VisualUtilities()
        {
            indentDepth = 0;
            dtElements = new DataTable();
            dtElements.Columns.Add("Type", typeof(string));
            dtElements.Columns.Add("Name", typeof(string));
            dtElements.Columns.Add("Level", typeof(int));
            dtElements.Columns.Add("Object", typeof(object));
        }

        public void GetVisualTree(Visual v)
        {
            string name = "";
            increaseIndent();

            if (v is FrameworkElement)
                name = ((FrameworkElement)v).Name;

            MakeEntry(v.GetType().ToString(), name, v);

            // recurse through the children
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(v); i++)
            {
                GetVisualTree((Visual)VisualTreeHelper.GetChild(v, i));
            }
            decreaseIndent();
        }

        public void GetLogicalTree(Object obj)
        {
            increaseIndent();

            try
            {
                if (obj is FrameworkElement)
                {
                    FrameworkElement fe = (FrameworkElement)obj;
                    if (fe.GetType().ToString() == "Microsoft.Windows.Controls.DataGrid")
                    {
                        DataGrid dg = fe as DataGrid;
                        foreach (DataGridColumn dgc in dg.Columns)
                        {
                            MakeEntry(dgc.GetType().ToString(), dgc.Header.ToString(), dgc);
                        }
                    }
                    MakeEntry(fe.GetType().ToString(), fe.Name, obj);

                    // recurse through the children
                    IEnumerable children = LogicalTreeHelper.GetChildren(fe);
                    foreach (object child in children)
                    {
                        GetLogicalTree(child);
                    }

                }
                else
                {
                    // stop recursing as we certainly can't have any more FrameworkElement children
                    MakeEntry(obj.GetType().ToString(), "", obj);
                }
            }
            catch (System.Exception ex)
            {
                throw new System.SystemException();
            }

            decreaseIndent();

        }
        private void MakeEntry(String sType, String sName, object ob)
        {
            if (sName == "")
                return;

            DataRow dr = dtElements.NewRow();
            dr.BeginEdit();
            UserControl uc = ob as UserControl;
            if (uc == null)
                dr["Type"] = sType;
            else
                dr["Type"] = typeof(UserControl).ToString();
            dr["Name"] = sName;
            dr["Level"] = indentDepth;
            dr["Object"] = ob;
            dr.EndEdit();
            dtElements.Rows.Add(dr);
        }

        private void increaseIndent()
        {
            indentDepth++;
        }

        private void decreaseIndent()
        {
            indentDepth--;
        }
    }

}
